﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
using FlowSequencer.Core.Sequencer;
using FlowSequencer.Core.FlowElements;

namespace FlowSequencer.Core.Tests
{
    [TestClass]
    public class SequencerTests
    {
        //[TestMethod]
        //public void CanInsertTasksToSequencer()
        //{
        //    ISequencer sequencer = new JohnsonSequencer(10);
        //    sequencer.InsertLine(new Line());
        //    sequencer.InsertLine(new Line());

        //    var outputFlow = sequencer.GetOutputFlow();
        //    Assert.AreEqual(new Flow(),outputFlow);
        //}

        [TestMethod]
        public void SequencerRunWhenLinesAreEmpty()
        {
            ISequencer sequencer = new JohnsonSequencer(4);
            sequencer.ComputeFlow();

            var line = LineGenerator.GetLine(0, 0);
            var status = sequencer.InsertLine(line);
            Assert.AreEqual(LineStatus.Correct, status);

            var status2 = sequencer.InsertLine(line);
            Assert.AreEqual(LineStatus.Correct, status2);

            sequencer.ComputeFlow();
        }

        //Feature removed
        //[TestMethod]
        //public void CanNotInsertMoreCyclesToLineThenMaxCyclesForFlow()
        //{
        //    ISequencer sequencer = new JohnsonSequencer(4);

        //    var line = LineGenerator.GetLine(2, 5);
        //    var status = sequencer.InsertLine(line);
        //    Assert.AreEqual(LineStatus.TooManyCycles, status);

        //    var line2 = LineGenerator.GetLine(2, 4);
        //    var status2 = sequencer.InsertLine(line2);
        //    Assert.AreEqual(LineStatus.Correct, status2);
        //}

        [TestMethod]
        public void CanGetOptiamlFlowTask()
        {
            ISequencer sequencer = new JohnsonSequencer(50); 
            var line1 = new Line() 
            {
                Tasks = new List<Task>() 
                {
                    new Task() { Name = "Z1", Index = 0, Cycles = 3 },
                    new Task() { Name = "Z2", Index = 1, Cycles = 3 },
                    new Task() { Name = "Z3", Index = 2, Cycles = 1 },
                    new Task() { Name = "Z4", Index = 3, Cycles = 5 },
                    new Task() { Name = "Z5", Index = 4, Cycles = 2 },
                } 
            };
            var line2 = new Line()
            {
                Tasks = new List<Task>() 
                {
                    new Task() { Name = "Z1", Index = 0, Cycles = 4 },
                    new Task() { Name = "Z2", Index = 1, Cycles = 1 },
                    new Task() { Name = "Z3", Index = 2, Cycles = 1 },
                    new Task() { Name = "Z4", Index = 3, Cycles = 3 },
                    new Task() { Name = "Z5", Index = 4, Cycles = 3 },
                }
            };

            sequencer.InsertLine(line1);
            sequencer.InsertLine(line2);
            sequencer.ComputeFlow();
            var flow = sequencer.GetOptimizedFlow();

            Assert.AreEqual("Z3", flow.Lines[0].Tasks[0].Name);
            Assert.AreEqual("Z5", flow.Lines[0].Tasks[1].Name);
            Assert.AreEqual("Z1", flow.Lines[0].Tasks[2].Name);
            Assert.AreEqual("Z4", flow.Lines[0].Tasks[3].Name);
            Assert.AreEqual("Z2", flow.Lines[0].Tasks[4].Name);

            Assert.AreEqual("", flow.Lines[1].Tasks[0].Name); // downtime
            Assert.AreEqual("Z3", flow.Lines[1].Tasks[1].Name);
            Assert.AreEqual("", flow.Lines[1].Tasks[2].Name); // downtime
            Assert.AreEqual("Z5", flow.Lines[1].Tasks[3].Name);

        }

        [TestMethod]
        public void CanGetOptiamlFlowTaskFor3Lines()
        {
            ISequencer sequencer = new JohnsonSequencer(50); 
            var line1 = new Line()
            {
                Tasks = new List<Task>() 
                {
                    new Task() { Name = "Z1", Index = 0, Cycles = 3 },
                    new Task() { Name = "Z2", Index = 1, Cycles = 3 },
                    new Task() { Name = "Z3", Index = 2, Cycles = 2 },
                    new Task() { Name = "Z4", Index = 3, Cycles = 2 },
                    new Task() { Name = "Z5", Index = 4, Cycles = 3 },
                }
            };
            var line2 = new Line()
            {
                Tasks = new List<Task>() 
                {
                    new Task() { Name = "Z1", Index = 0, Cycles = 1 },
                    new Task() { Name = "Z2", Index = 1, Cycles = 2 },
                    new Task() { Name = "Z3", Index = 2, Cycles = 2 },
                    new Task() { Name = "Z4", Index = 3, Cycles = 1 },
                    new Task() { Name = "Z5", Index = 4, Cycles = 1 },
                }
            };

            var line3 = new Line()
            {
                Tasks = new List<Task>() 
                {
                    new Task() { Name = "Z1", Index = 0, Cycles = 3 },
                    new Task() { Name = "Z2", Index = 1, Cycles = 1 },
                    new Task() { Name = "Z3", Index = 2, Cycles = 1 },
                    new Task() { Name = "Z4", Index = 3, Cycles = 3 },
                    new Task() { Name = "Z5", Index = 4, Cycles = 1 },
                }
            };

            sequencer.InsertLine(line1);
            sequencer.InsertLine(line2);
            sequencer.InsertLine(line3);

            sequencer.ComputeFlow();
            var flow = sequencer.GetOptimizedFlow();
            Assert.AreEqual("Z4", flow.Lines[0].Tasks[0].Name);
            Assert.AreEqual("Z1", flow.Lines[0].Tasks[1].Name);
            Assert.AreEqual("Z2", flow.Lines[0].Tasks[2].Name);
            Assert.AreEqual("Z3", flow.Lines[0].Tasks[3].Name);
            Assert.AreEqual("Z5", flow.Lines[0].Tasks[4].Name);

            Assert.AreEqual("", flow.Lines[1].Tasks[0].Name);
            Assert.AreEqual("Z4", flow.Lines[1].Tasks[1].Name);
            Assert.AreEqual("", flow.Lines[1].Tasks[2].Name);
            Assert.AreEqual("Z1", flow.Lines[1].Tasks[3].Name);
            Assert.AreEqual("", flow.Lines[1].Tasks[4].Name);
            Assert.AreEqual("Z2", flow.Lines[1].Tasks[5].Name);
        }
    }
}
